#ifndef __GDT_H_
#define __GDT_H_

#define SS_R0_CODE 0x08
#define SS_R0_DATA 0x10
#define SS_R3_CODE 0x1B
#define SS_R3_DATA 0x23
#define SS_TSS 0x28

/* data type */
#define SEG_DATA_RD         0x00 // Read-Only
#define SEG_DATA_RDA        0x01 // Read-Only, accessed
#define SEG_DATA_RDWR       0x02 // Read/Write
#define SEG_DATA_RDWRA      0x03 // Read/Write, accessed
#define SEG_DATA_RDEXPD     0x04 // Read-Only, expand-down
#define SEG_DATA_RDEXPDA    0x05 // Read-Only, expand-down, accessed
#define SEG_DATA_RDWREXPD   0x06 // Read/Write, expand-down
#define SEG_DATA_RDWREXPDA  0x07 // Read/Write, expand-down, accessed

/* code type */
#define SEG_CODE_EX         0x08 // Execute-Only
#define SEG_CODE_EXA        0x09 // Execute-Only, accessed
#define SEG_CODE_EXRD       0x0A // Execute/Read
#define SEG_CODE_EXRDA      0x0B // Execute/Read, accessed
#define SEG_CODE_EXC        0x0C // Execute-Only, conforming
#define SEG_CODE_EXCA       0x0D // Execute-Only, conforming, accessed
#define SEG_CODE_EXRDC      0x0E // Execute/Read, conforming
#define SEG_CODE_EXRDCA     0x0F // Execute/Read, conforming, accessed

#define SET_TYPE(x)         ((x) << 8)
#define SET_CODE_DATA(x)    ((x) << 12)
#define SET_DPL(x)          ((x) << 13)
#define SET_PRESENT(x)      ((x) << 15)
#define SET_AVL(x)          ((x) << 20)
#define SET_64BITS(x)       ((x) << 21)
#define SET_32BITS(x)       ((x) << 22)
#define SET_4K_G(x)         ((x) << 23)

#define SEG_LIMIT_L(x)      ((x) & 0x0FFFF)
#define SEG_LIMIT_H(x)      ((x) & 0xF0000)
#define SEG_BASE_L(x)       (((x) & 0x0000FFFF) << 16)
#define SEG_BASE_M(x)       (((x) & 0x00FF0000) >> 16)
#define SEG_BASE_H(x)       (((x) & 0xFF000000))

#define R0_CODE             SET_TYPE(SEG_CODE_EXRD) |\
                            SET_CODE_DATA(1) |\
                            SET_DPL(0) |\
                            SET_PRESENT(1) |\
                            SET_AVL(0) |\
                            SET_64BITS(0) |\
                            SET_32BITS(1) |\
                            SET_4K_G(1)

#define R0_DATA             SET_TYPE(SEG_DATA_RDWR) |\
                            SET_CODE_DATA(1) |\
                            SET_DPL(0) |\
                            SET_PRESENT(1) |\
                            SET_AVL(0) |\
                            SET_64BITS(0) |\
                            SET_32BITS(1) |\
                            SET_4K_G(1)

#define R3_CODE             SET_TYPE(SEG_CODE_EXRD) |\
                            SET_CODE_DATA(1) |\
                            SET_DPL(3) |\
                            SET_PRESENT(1) |\
                            SET_AVL(0) |\
                            SET_64BITS(0) |\
                            SET_32BITS(1) |\
                            SET_4K_G(1)
                            
#define R3_DATA             SET_TYPE(SEG_DATA_RDWR) |\
                            SET_CODE_DATA(1) |\
                            SET_DPL(3) |\
                            SET_PRESENT(1) |\
                            SET_AVL(0) |\
                            SET_64BITS(0) |\
                            SET_32BITS(1) |\
                            SET_4K_G(1)

#define TSS_AVAILABLE 9

#define TSS                 SET_TYPE(TSS_AVAILABLE) |\
                            SET_CODE_DATA(0) |\
                            SET_DPL(0) |\
                            SET_PRESENT(1)
#endif
